package com.jindy.module.oaInductionApproval.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.jindy.activiti.service.IProcessService;
import com.jindy.common.constant.Constants;
import com.jindy.common.core.domain.entity.SysDept;
import com.jindy.common.exception.base.BaseException;
import com.jindy.common.utils.DateUtils;
import com.jindy.common.utils.SecurityUtils;
import com.jindy.common.utils.StringUtils;
import com.jindy.jpush.utils.UniJpushUtils;
import com.jindy.module.approvalRecord.domain.ApprovalRecord;
import com.jindy.module.approvalRecord.mapper.ApprovalRecordMapper;
import com.jindy.module.jpush.mapper.JpushMapper;
import com.jindy.module.oaLeaveApproval.domain.SyOaLeaveApproval;
import com.jindy.module.oaLeaveApproval.service.impl.SyOaLeaveApprovalServiceImpl;
import com.jindy.module.oacopy.service.ISyOaCopyService;
import com.jindy.module.oacopyconfig.domain.SyOaCopyConfig;
import com.jindy.module.oacopyconfig.mapper.SyOaCopyConfigMapper;
import com.jindy.module.serialNum.service.ISySerialNumTService;
import com.jindy.module.syTableRecord.service.ISyTableRecordTService;
import com.jindy.system.domain.SysUserRoleDeptInfo;
import com.jindy.system.service.ISysDeptService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.jindy.module.oaInductionApproval.mapper.SyOaInductionMapper;
import com.jindy.module.oaInductionApproval.domain.SyOaInduction;
import com.jindy.module.oaInductionApproval.service.ISyOaInductionService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;

/**
 * 入职审批Service业务层处理
 * 
 * @author jindy
 * @date 2023-05-29
 */
@Service
public class SyOaInductionServiceImpl implements ISyOaInductionService 
{
    private static final Logger LOGGER = LoggerFactory.getLogger(SyOaInductionServiceImpl.class);

    @Autowired
    private SyOaInductionMapper syOaInductionMapper;

    @Resource
    private ISysDeptService sysDeptService;

    /**
     * 审批流
     */
    @Autowired
    private IProcessService processService;

    /**
     * 设备Mapper
     */
    @Resource
    private JpushMapper jpushMapper;

    /**
     * 生成流水单号Service
     */
    @Resource
    private ISySerialNumTService serialNumTService;

    /**
     * 存储表Service
     */
    @Resource
    private ISyTableRecordTService iSyTableRecordTService;

    /**
     * 配置表
     */
    @Resource
    private SyOaCopyConfigMapper syOaCopyConfigMapper;

    /**
     * 抄送Service
     */
    @Resource
    private ISyOaCopyService syOaCopyService;

    /**
     * 生成流水单号Service
     */
    @Resource
    private ApprovalRecordMapper approvalRecordMapper;

    /**
     * 查询入职审批
     * 
     * @param id 入职审批主键
     * @return 入职审批
     */
    @Override
    public SyOaInduction selectSyOaInductionById(Long id)
    {
        return syOaInductionMapper.selectSyOaInductionById(id);
    }

    /**
     * 查询入职审批列表
     * 
     * @param syOaInduction 入职审批
     * @return 入职审批
     */
    @Override
    public List<SyOaInduction> selectSyOaInductionList(SyOaInduction syOaInduction)
    {
        if (!SecurityUtils.isAdmin(SecurityUtils.getLoginUser().getUser().getUserId())) {
            syOaInduction.setCreateBy(SecurityUtils.getUsername());
        }
        List<SyOaInduction> list = syOaInductionMapper.selectSyOaInductionList(syOaInduction);
        if (!CollectionUtils.isEmpty(list)) {
            list.forEach(item -> {
                try {
                    processService.richProcessField(item);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }
        return list;
//        return syOaInductionMapper.selectSyOaInductionList(syOaInduction);
    }

    /**
     * 新增入职审批
     * 
     * @param syOaInduction 入职审批
     * @return 结果
     */
    @Override
    public int insertSyOaInduction(SyOaInduction syOaInduction)
    {
        // 生成流水单号
        String serialNum = serialNumTService.generateSerialNum("RZSP");
        if (StringUtils.isBlank(serialNum)) {
            throw new BaseException("新增入职审批-获取入职单号失败");
        }
        syOaInduction.setSerialNum(serialNum);
        syOaInduction.setBusinessStatus(Constants.DRAFT);
        syOaInduction.setCreateTime(DateUtils.getNowDate());
        iSyTableRecordTService.saveEntityAndTable(syOaInduction,serialNum);
        return syOaInductionMapper.insertSyOaInduction(syOaInduction);
    }

    /**
     * 修改入职审批
     * 
     * @param syOaInduction 入职审批
     * @return 结果
     */
    @Override
    public int updateSyOaInduction(SyOaInduction syOaInduction)
    {
        syOaInduction.setUpdateTime(DateUtils.getNowDate());
        return syOaInductionMapper.updateSyOaInduction(syOaInduction);
    }

    /**
     * 批量删除入职审批
     * 
     * @param ids 需要删除的入职审批主键
     * @return 结果
     */
    @Override
    public int deleteSyOaInductionByIds(Long[] ids)
    {
        return syOaInductionMapper.deleteSyOaInductionByIds(ids);
    }

    /**
     * 删除入职审批信息
     * 
     * @param id 入职审批主键
     * @return 结果
     */
    @Override
    public int deleteSyOaInductionById(Long id)
    {
        return syOaInductionMapper.deleteSyOaInductionById(id);
    }

    /**
     * 提交申请
     * @param induction
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void submitApply(SyOaInduction induction) throws Exception {
        // 初始化值
        Map<String, Object> variables = createVariables(induction);
        // 启动流程
        processService.submitApply(induction, "induction", variables);
        // 添加抄送人
        syOaCopyService.addCopyUsers("RZSP_LEADER",induction.getId());
        //新增审批记录
        List<Long> longs = addApprovalRecord(induction, variables);
        // 通知审批人
        sendApproveMessage(longs);
        induction.setBusinessStatus(Constants.APPROVE);
        updateSyOaInduction(induction);
    }


    /**
     * 新增审批记录
     * @param induction
     * @param map
     * @return
     */
    private List<Long> addApprovalRecord(SyOaInduction induction, Map<String, Object> map) {
        List<Long> list = new ArrayList<>();
        int sequence = 1;
        //  发起人
        ApprovalRecord firstApprovalRecord = getApprovalRecord(induction);
        firstApprovalRecord.setSequence(sequence);
        firstApprovalRecord.setApprovalStatus(Constants.COMPLETED);
        firstApprovalRecord.setTypeOperation(Constants.AGREE);
        firstApprovalRecord.setBusinessStatus(Constants.APPROVE);
        firstApprovalRecord.setApproverId(Long.valueOf(induction.getApplyUserId()));
        firstApprovalRecord.setApproverName(induction.getApplyUserName());
        approvalRecordMapper.insertApprovalRecord(firstApprovalRecord);

        sequence++;
        //  第一审批人
        ApprovalRecord secondApprovalRecord = getApprovalRecord(induction);
        secondApprovalRecord.setSequence(sequence);
        secondApprovalRecord.setApprovalStatus(Constants.APPROVE);
        String hrId=map.get("hrId").toString();
        secondApprovalRecord.setApproverId(Long.parseLong(hrId));
        secondApprovalRecord.setApproverName((String) map.get("hr"));
        approvalRecordMapper.insertApprovalRecord(secondApprovalRecord);
        list.add(Long.parseLong(hrId));

        sequence++;
        //  第二审批人
        ApprovalRecord thirdApprovalRecord = getApprovalRecord(induction);
        thirdApprovalRecord.setSequence(sequence);
        thirdApprovalRecord.setApprovalStatus(Constants.APPROVE);
        thirdApprovalRecord.setApproverId((Long) map.get("deptleaderId"));
        thirdApprovalRecord.setApproverName((String) map.get("deptleader"));
        approvalRecordMapper.insertApprovalRecord(thirdApprovalRecord);
        list.add((Long) map.get("deptleaderId"));

        return list;
    }

    /**
     * 获取审批记录对象
     *
     * @param induction
     * @return
     */
    private ApprovalRecord getApprovalRecord(SyOaInduction induction) {
        ApprovalRecord approvalRecord = new ApprovalRecord();
        approvalRecord.setSerialNum(induction.getSerialNum());
        approvalRecord.setUserId(Long.valueOf(induction.getApplyUserId()));
        approvalRecord.setOrderId(induction.getId());
        approvalRecord.setUserName(induction.getApplyUserName());
        approvalRecord.setUpdateTime(DateUtils.parseDate(DateUtils.getTime()));
        approvalRecord.setUpdateBy(induction.getApplyUserName());
        approvalRecord.setCreateBy(induction.getApplyUserName());
        approvalRecord.setCreateTime(DateUtils.parseDate(DateUtils.getTime()));
        return approvalRecord;
    }

    /**
     * 初始化值
     * @param induction
     * @return
     */
    private Map<String, Object> createVariables(SyOaInduction induction) {
        Map<String, Object> var = new HashMap<>(500);

        //hr审批
        SyOaCopyConfig syOaCopyConfig = new SyOaCopyConfig();
        syOaCopyConfig.setNumber("RZSP_HR");
        List<SyOaCopyConfig> syOaCopyConfigs = syOaCopyConfigMapper.selectSyOaCopyConfigList(syOaCopyConfig);
        if (CollectionUtils.isEmpty(syOaCopyConfigs)) {
            throw new BaseException("createVariables", "获取HR失败");
        }
        var.put("hr",syOaCopyConfigs.get(0).getCopyUserName());
        var.put("hrId",syOaCopyConfigs.get(0).getCopyUserId());

        // 部门主管审批
        SysDept sysDept=sysDeptService.selectDeptById(induction.getDeptId());
        if(sysDept.getLeaderId() == null){
            throw new BaseException("入职审批-查询部门主管为null");
        }
        var.put("deptleader",sysDept.getLeader());
        var.put("deptleaderId",sysDept.getLeaderId());

        return var;
    }

    /**
     * 给审批人推送消息
     * @param addJpushList
     */
    private void sendApproveMessage(List<Long> addJpushList) {
        try {
            List<String> addRegIds = jpushMapper.selectRegistrationIdsByUserIds(addJpushList);
            if (!CollectionUtils.isEmpty(addRegIds)){
                UniJpushUtils.sendApproveMessage(addRegIds);
            }
        } catch (Exception e) {
            LOGGER.error("入职审批审批人推送通知失败",e);
        }
    }

}
